#ifndef SESSION_H
#define SESSION_H

#include "msg_node.h"

#include <atomic>
#include <cstdint>
#include <memory>
#include <string>
#include <queue>
#include <mutex>

#include <boost/asio/io_context.hpp>
#include <boost/asio/ip/tcp.hpp>


class Server;

class Session:public std::enable_shared_from_this<Session>
{
public:
    Session(boost::asio::io_context& io, Server* server);
    ~Session() { Close(); };
    void Start();
    void Close();
    void Send(const char* data, uint32_t len, uint32_t id);
    boost::asio::ip::tcp::socket& GetSocket() { return m_sock; }
    const std::string& GetUUID()const { return m_uuid; }
    std::shared_ptr<RecvNode> GetRecvNode() { return m_recv_node; }

private:
    void _HeadWrite(boost::system::error_code ec, std::size_t len, std::shared_ptr<Session> self);

private:
    boost::asio::io_context& m_iocontext;
    Server* m_server;
    boost::asio::ip::tcp::socket m_sock;
    std::string m_uuid;
    std::atomic_bool m_is_closed{false};

    std::mutex m_send_mutex;
    std::queue<std::shared_ptr<SendNode>> m_send_queue;
    std::shared_ptr<RecvNode> m_recv_node;
};


class LogicNode
{
public:
    LogicNode(std::shared_ptr<Session> session)
    :m_session(std::move(session)) {}

    std::shared_ptr<Session> GetSession() { return m_session; }
private:
    std::shared_ptr<Session> m_session;
};

#endif // SESSION_H
